package com.sarc.games.focus;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Random;
import java.util.concurrent.locks.ReentrantLock;

import javax.microedition.khronos.opengles.GL10;

import com.sarc.games.GameAction;
import com.sarc.games.focus.Square.SquareStatus;

public class Grid
{
	int size;
	long frameTime;
	boolean isRotating;
	float topLeftPointX, topLeftPointY;
	PopulateAction populateAction;
	
	Random rand = new Random(Calendar.getInstance().getTimeInMillis());
	ArrayList<ArrayList<Square>> grid;
	
	public Grid(int size)
	{
		frameTime = 0;
		this.size = size;
		grid = new ArrayList< ArrayList<Square>>();
		for (int i = 0; i < size; i++)
		{
			grid.add(new ArrayList<Square>());
			for (int j = 0; j < size; j++)
			{
				grid.get(i).add(new Square((float)j, (float)i));
			}
		}
		topLeftPointX = topLeftPointY = -(float)size/2f;
		populateAction = null;
		isRotating = false;
	}
	
	public void refreshGrid(double newEnergyLevel)
	{
		for (int i = 0; i < size; i++)
			for (int j = 0; j < size; j++)
				grid.get(i).get(j).setEnergyLevel(newEnergyLevel);
	}
		
	public void populate(long time)
	{
		ArrayList<Square> newRow = new ArrayList<Square>();
		for (int i = 0; i < size; i++)
		{
			Square newColSquare = new Square(size-1, i);
			newColSquare.moveTo(size, i , time);
			Square newRowSquare = new Square(i, size-1);
			newRowSquare.moveTo(i, size , time);
			newRow.add(newRowSquare);
			grid.get(i).add(newColSquare);
		}
		Square newCornerSquare = new Square(size-1, size-1);
		newCornerSquare.moveTo(size, size, time);
		newRow.add(newCornerSquare);
		grid.add(newRow);	
			
		populateAction = new PopulateAction(size, size+1, time);
		size++;
	}
	
	public void rotateWhole(boolean clockwise, long time)
	{

	}
	
	public void shuffleGrid(long time)
	{
		ArrayList<ArrayList<Square>> newGrid = new ArrayList<ArrayList<Square>>();
		ArrayList<Square> squareList = new ArrayList<Square>();
		for (int i = 0; i < size; i++)
		{
			for (int j = 0 ; j < size; j++)
			{
				squareList.add(grid.get(j).get(i));
			}
		}
		
		for (int i = 0; i < size; i++)
		{
			ArrayList<Square> row = new ArrayList<Square>();
			for (int j = 0; j < size; j++)
			{
				int oldIndex = rand.nextInt(squareList.size());
				Square square = squareList.get(oldIndex);
				squareList.remove(oldIndex);
				
				square.moveTo((float)j , (float)i, time);
				row.add(square);
			}
			newGrid.add(row);
		}
		grid = newGrid;
	}
		
	public void rotateAllSquare(boolean clockwise, long time)
	{
		for (ArrayList<Square> row : grid)
			for (Square square : row)
			{
				square.addRotation(clockwise?-90f:90f, time);
			}
	}
	
	public void randomGive(double energy, long time)
	{
		grid.get(rand.nextInt(size)).get(rand.nextInt(size)).giveEnergy(energy, time);
	}
	
	public void randomTake(double energy, long time)
	{
		grid.get(rand.nextInt(size)).get(rand.nextInt(size)).takeEnergy(energy, time);
	}
	
	public void giveAt(int x, int y, double energy, long time)
	{
		if (x < size && y < size)
		{
			grid.get(x).get(y).giveEnergy(energy, time);
		}
	}
	
	public void takeAt(int x, int y, double energy, long time)
	{
		if (x < size && y < size)
		{
			grid.get(x).get(y).takeEnergy(energy, time);
		}
	}
	
	public SquareStatus update(Energy energySource, long frameTime, ColorManager colorManager)
	{
		if (populateAction != null)
		{
			topLeftPointX = topLeftPointY = populateAction.getNewPosition(frameTime);
			if (populateAction.shouldRemove())
			{
				populateAction = null;
			}
		}
		
		SquareStatus gridStatus = SquareStatus.NORMAL;
		for (ArrayList<Square> row : grid)
			for (Square square : row)
				{
					SquareStatus sqStatus = square.update(frameTime, colorManager);
					if (sqStatus != SquareStatus.NORMAL)
					{
						gridStatus = sqStatus;
					}
				}
		return gridStatus;
	}

	public void render(GL10 gl)
	{
		gl.glPushMatrix();
		gl.glTranslatef(topLeftPointX, topLeftPointY, 0);
		for (int i = 0; i < grid.size(); i++)
		{
			ArrayList<Square> row = grid.get(i);
			for (int j = 0; j < row.size(); j++)
			{
				row.get(j).render(gl);	
			}
		}
		gl.glPopMatrix();
	}
	
	private class PopulateAction extends GameAction
	{
		final float oldSize, newSize;
		float outSize;
		public PopulateAction(float oldSize, float newSize, long time)
		{
			super(time);
			this.newSize = newSize;
			this.oldSize = this.outSize = oldSize;
		}
		
		public float getNewPosition(long time)
		{
			resolve(time);
			outSize += (newSize - oldSize) * (float)deltaProgress();
			return -outSize/2;
		}
	}
	
	public enum GridActionType
	{
		GIVE, TAKE, RANDOM_GIVE, RANDOM_TAKE, POPULATE, SHRINK, REFRESH, RADIATE, SWIRL, SHUFFLE, ROTATE_SQUARE, ROTATE_WHOLE
	}
}
